// *********************************************************************
//
// BrianHG_DDR3_PLL.sv clock generator with DQS CLK phase
// control for write leveling, RQD 90 degree clock, and
// CMD_CLK system clock which can be configured to: 
//
//
// Version 1.2, August 26, 2021
//
// This version now output the individual DDR3_CLK, DDR3_CLK_WDQ, DDR3_CLK_RDQ,
// ***NEW : DDR3_CLK_50, DDR3_CLK_25, plus the original CMD_CLK which will now equal
//          DDR3_CLK, DDR3_CLK_50, or DDR3_CLK_25 depending on the interface speed.
//          _50 = Half frequency, _25 = Quarter frequency.
//
// V1.2: Added support for Cyclone V / Arria V / Stratix V style PLL support.
//
//
// Written by Brian Guralnick.
// For public use.
// Leave questions in the https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/
//
// *********************************************************************

module BrianHG_DDR3_PLL #(

parameter string     FPGA_VENDOR             = "Altera",       // Use ALTERA, INTEL, LATTICE or XILINX.
parameter string     FPGA_FAMILY             = "MAX 10",       // (USE "SIM" for RTL simulation bypassing any HW dependent functions) With Altera, use Cyclone III, Cyclone IV, Cyclone V, MAX 10,....

// ****************  System clock generation and operation.

parameter int        CLK_KHZ_IN              = 50000,          // PLL source input clock frequency in KHz.
parameter int        CLK_IN_MULT             = 32,             // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,              // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.

parameter int        DDR_TRICK_MTPS_CAP      = 0,              // 0=off, Set a false PLL DDR data rate for the compiler to allow FPGA overclocking.  ***DO NOT USE.

parameter string     INTERFACE_SPEED         = "Full",         // Either "Full", "Half", or "Quarter" speed for the user interface clock.
                                                               // This will effect the controller's interface CMD_CLK output port frequency.
                                                               // "Full" means that CMD_CLK = DDR3_CLK, "Half" means CMD_CLK is half speed of DDR3_CLK...

parameter int        DDR3_WDQ_PHASE          = 270,            // 90, 0,45,90,...270 Select the write and write DQS output clock phase relative to the DDR3_CLK/CK#
parameter int        DDR3_RDQ_PHASE          = 0               // 45, 0,45,90,...270 Select the read latch clock for the read data and DQS input relative to the DDR3_CLK.
)
(
   RST_IN,                // Active high reset input.
   RST_OUT,               // Low after reset timer has been released
   CLK_IN,                // Input clock.

   DDR3_CLK,              // DDR3 CK clock running at 1/2 the DQ rate.
   DDR3_CLK_WDQ,          // DDR3 write data clock 90 degree out of phase running at 1/2 the DQ rate.
   DDR3_CLK_RDQ,          // DDR3 phase adjustable read data input clock running at 1/2 the DQ rate.
   DDR3_CLK_50,           // DDR3 clock running at 1/4 the DQ rate.
   DDR3_CLK_25,           // DDR3 clock running at 1/8 the DQ rate.

   CMD_CLK,               // Ram controller interface clock running at DDR3_CLK, or 1/2 DDR3_CLK, or 1/4 DDR3_CLK
   PLL_LOCKED,            // High when the PLL is functioning.
   
   phase_step,            // Step a phase.
   phase_updn,            // Step direction.
   phase_sclk,            // phase interface clock.
   phase_done             // Goes low when ready.
);

input        RST_IN,CLK_IN;
(*preserve*) output logic RST_OUT;
output logic DDR3_CLK,DDR3_CLK_WDQ,DDR3_CLK_RDQ,DDR3_CLK_50,DDR3_CLK_25,CMD_CLK,PLL_LOCKED;
logic        RST_PLL;
input        phase_step,phase_updn,phase_sclk;
output       phase_done;


// ALTERA - Again with string stored inside a non-string bug.... WHY????????????
// I could have supported any arbitrary frequency, but you locked me into a tiny fixed table.
// Just be glad you are not LATTICE which places PLL parameters inside /* comments */ where I cant even
// pass a parameter through.

localparam  RCF = (CLK_KHZ_IN==50000)  ? "50.0 MHz"  :
                  (CLK_KHZ_IN==25000)  ? "25.0 MHz"  :
                  (CLK_KHZ_IN==75000)  ? "75.0 MHz"  :
                  (CLK_KHZ_IN==100000) ? "100.0 MHz" :
                  (CLK_KHZ_IN==125000) ? "125.0 MHz" :
                  (CLK_KHZ_IN==150000) ? "150.0 MHz" : 0 ;


// Verify that the 'INTERFACE_SPEED' is equal to "Full" ,'Half', or 'Quarter'.
generate
         if (INTERFACE_SPEED[0]!="F" && INTERFACE_SPEED[0]!="f" &&
             INTERFACE_SPEED[0]!="H" && INTERFACE_SPEED[0]!="h" &&
             INTERFACE_SPEED[0]!="Q" && INTERFACE_SPEED[0]!="q"     )  initial begin

// **********************************************
// ***  Unknown INTERFACE_SPEED *****************
// **********************************************
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("********************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .INTERFACE_SPEED(\"%s\") is not supported. ***",INTERFACE_SPEED);
$warning("*** Only \"Full\", \"Half\", and \"Quarter\" speeds are supported.           ***");
$warning("********************************************************************************");
$error;
$stop;
end

if (RCF == 0 )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("*******************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .CLK_KHZ_IN(\"%s\") is not supported with  ***",12'(CLK_KHZ_IN));
$warning("*** Cyclone V PLL.  Only 25000, 50000, 75000, 100000, 125000, 150000 KHz    ***");
$warning("*** are supported.                                                          ***");
$warning("*******************************************************************************");
$error;
$stop;
end

if (CLK_IN_DIV!=2 && CLK_IN_DIV!=4 && CLK_IN_DIV!=6 && CLK_IN_DIV!=8 && CLK_IN_DIV!=10 && CLK_IN_DIV!=12)  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("**************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .CLK_IN_DIV(%d) is not supported.     ***",8'(CLK_IN_DIV));
$warning("*** Only a divider setting of 2,4,6,8,10, or 12 are allowed.           ***");
$warning("**************************************************************************");
$error;
$stop;
end

if (CLK_IN_MULT[0] || (CLK_IN_MULT<20) || (CLK_IN_MULT>48) )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("**************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .CLK_IN_MULT(%d) is not supported.    ***",8'(CLK_IN_MULT));
$warning("*** Only even multiplier numbers between 20 and 48 are allowed.        ***");
$warning("**************************************************************************");
$error;
$stop;
end

endgenerate


// **************************************************
// Make the CMD_CLK_DIV = 1x, 2x, or 4x CLK_IN_DIV
// **************************************************

localparam CMD_CLK_DIV = CLK_IN_DIV * (1 + (INTERFACE_SPEED[0]=="H" || INTERFACE_SPEED[0]=="h") + (3*(INTERFACE_SPEED[0]=="Q" || INTERFACE_SPEED[0]=="q")) ) ;

localparam int PLL1_OUT_TRUE_KHZ    = (CLK_KHZ_IN * CLK_IN_MULT / CLK_IN_DIV  ) ;    // Register the true DDR3_CLK frequency in KHz.
localparam int PLL1_OUT_CMD_CLK_KHZ = (CLK_KHZ_IN * CLK_IN_MULT / CMD_CLK_DIV ) ;    // Register the true CMD_CLK frequency in KHz.

// Generate a phony input clock frequency for the PLL to report to your FPGA compiler
// so it will believe the DDR3_DQ/DQS bus is working within the set rate.  This will
// cause improper timing reports and poor system stability.

localparam int PLL1_KHZ_IN_TRICK = CLK_KHZ_IN * DDR_TRICK_MTPS_CAP / PLL1_OUT_TRUE_KHZ * 500 ;
 
// Select the PLL1 source clock input frequency and input period in picoseconds based on DDR_TRICK_MTPS_CAP setting.
localparam int PLL1_in_KHz = (DDR_TRICK_MTPS_CAP==0 || DDR_TRICK_MTPS_CAP>(PLL1_OUT_TRUE_KHZ/500)) ? CLK_KHZ_IN : PLL1_KHZ_IN_TRICK ;
localparam int PLL1_inps   = (1.0E9 / PLL1_in_KHz) ; 



// ********************* Generate warning if the DDR_TRICK_MTPS_CAP is enabled. *********************
generate
if (DDR_TRICK_MTPS_CAP!=0 ) initial begin
if (DDR_TRICK_MTPS_CAP>=(PLL1_OUT_TRUE_KHZ/500)) begin
$warning("*****************************");
$warning("*** BrianHG_DDR3_PLL Info ***");
$warning("************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .DDR_TRICK_MTPS_CAP setting of (%d) ***",12'(DDR_TRICK_MTPS_CAP));
$warning("*** was not used since the DDR MTPS frequency is only %d MTPS.     ***",12'(PLL1_OUT_TRUE_KHZ/500));
$warning("************************************************************************");
end else begin
$warning("********************************");
$warning("*** BrianHG_DDR3_PLL WARNING ***");
$warning("*******************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .DDR_TRICK_MTPS_CAP setting of (%d)        ***",12'(DDR_TRICK_MTPS_CAP));
$warning("*** is in use since the true DDR3_DQ MTPS frequency is higher at %d MTPS. ***",12'(PLL1_OUT_TRUE_KHZ/500));
$warning("*** %s is being falsely instructed that the DDR3 clock is running      ***",FPGA_VENDOR);
$warning("*** slower to allow full compilation for DDR_DQ/DQS port speed limit.  The  ***");
$warning("*** timing report will only be accurate as long as the PLL source clock has ***");
$warning("*** the proper frequency set in the .sdc file.  Make sure this is EXACTLY   ***");
$warning("*** what you want to do.  Proper design functionality is not guaranteed.    ***");
$warning("*******************************************************************************");
end
end
endgenerate


localparam  DDR3_WDQ_PHASE_ps = (((1000000 / ( PLL1_in_KHz/1000 * CLK_IN_MULT / CLK_IN_DIV )) * DDR3_WDQ_PHASE / 360) ) ;
localparam  DDR3_RDQ_PHASE_ps = (((1000000 / ( PLL1_in_KHz/1000 * CLK_IN_MULT / CLK_IN_DIV )) * DDR3_RDQ_PHASE / 360) ) ;


localparam  int Altera_Dummy_String [0:3999] = '{ // Seriously, this is the only way...  I feel like an idiot making this public...
"0000","0001","0002","0003","0004","0005","0006","0007","0008","0009","0010","0011","0012","0013","0014","0015","0016","0017","0018","0019","0020","0021","0022","0023","0024","0025","0026","0027","0028","0029","0030","0031","0032","0033","0034","0035","0036","0037","0038","0039","0040","0041","0042","0043","0044","0045","0046","0047","0048","0049",
"0050","0051","0052","0053","0054","0055","0056","0057","0058","0059","0060","0061","0062","0063","0064","0065","0066","0067","0068","0069","0070","0071","0072","0073","0074","0075","0076","0077","0078","0079","0080","0081","0082","0083","0084","0085","0086","0087","0088","0089","0090","0091","0092","0093","0094","0095","0096","0097","0098","0099",
"0100","0101","0102","0103","0104","0105","0106","0107","0108","0109","0110","0111","0112","0113","0114","0115","0116","0117","0118","0119","0120","0121","0122","0123","0124","0125","0126","0127","0128","0129","0130","0131","0132","0133","0134","0135","0136","0137","0138","0139","0140","0141","0142","0143","0144","0145","0146","0147","0148","0149",
"0150","0151","0152","0153","0154","0155","0156","0157","0158","0159","0160","0161","0162","0163","0164","0165","0166","0167","0168","0169","0170","0171","0172","0173","0174","0175","0176","0177","0178","0179","0180","0181","0182","0183","0184","0185","0186","0187","0188","0189","0190","0191","0192","0193","0194","0195","0196","0197","0198","0199",
"0200","0201","0202","0203","0204","0205","0206","0207","0208","0209","0210","0211","0212","0213","0214","0215","0216","0217","0218","0219","0220","0221","0222","0223","0224","0225","0226","0227","0228","0229","0230","0231","0232","0233","0234","0235","0236","0237","0238","0239","0240","0241","0242","0243","0244","0245","0246","0247","0248","0249",
"0250","0251","0252","0253","0254","0255","0256","0257","0258","0259","0260","0261","0262","0263","0264","0265","0266","0267","0268","0269","0270","0271","0272","0273","0274","0275","0276","0277","0278","0279","0280","0281","0282","0283","0284","0285","0286","0287","0288","0289","0290","0291","0292","0293","0294","0295","0296","0297","0298","0299",
"0300","0301","0302","0303","0304","0305","0306","0307","0308","0309","0310","0311","0312","0313","0314","0315","0316","0317","0318","0319","0320","0321","0322","0323","0324","0325","0326","0327","0328","0329","0330","0331","0332","0333","0334","0335","0336","0337","0338","0339","0340","0341","0342","0343","0344","0345","0346","0347","0348","0349",
"0350","0351","0352","0353","0354","0355","0356","0357","0358","0359","0360","0361","0362","0363","0364","0365","0366","0367","0368","0369","0370","0371","0372","0373","0374","0375","0376","0377","0378","0379","0380","0381","0382","0383","0384","0385","0386","0387","0388","0389","0390","0391","0392","0393","0394","0395","0396","0397","0398","0399",
"0400","0401","0402","0403","0404","0405","0406","0407","0408","0409","0410","0411","0412","0413","0414","0415","0416","0417","0418","0419","0420","0421","0422","0423","0424","0425","0426","0427","0428","0429","0430","0431","0432","0433","0434","0435","0436","0437","0438","0439","0440","0441","0442","0443","0444","0445","0446","0447","0448","0449",
"0450","0451","0452","0453","0454","0455","0456","0457","0458","0459","0460","0461","0462","0463","0464","0465","0466","0467","0468","0469","0470","0471","0472","0473","0474","0475","0476","0477","0478","0479","0480","0481","0482","0483","0484","0485","0486","0487","0488","0489","0490","0491","0492","0493","0494","0495","0496","0497","0498","0499",
"0500","0501","0502","0503","0504","0505","0506","0507","0508","0509","0510","0511","0512","0513","0514","0515","0516","0517","0518","0519","0520","0521","0522","0523","0524","0525","0526","0527","0528","0529","0530","0531","0532","0533","0534","0535","0536","0537","0538","0539","0540","0541","0542","0543","0544","0545","0546","0547","0548","0549",
"0550","0551","0552","0553","0554","0555","0556","0557","0558","0559","0560","0561","0562","0563","0564","0565","0566","0567","0568","0569","0570","0571","0572","0573","0574","0575","0576","0577","0578","0579","0580","0581","0582","0583","0584","0585","0586","0587","0588","0589","0590","0591","0592","0593","0594","0595","0596","0597","0598","0599",
"0600","0601","0602","0603","0604","0605","0606","0607","0608","0609","0610","0611","0612","0613","0614","0615","0616","0617","0618","0619","0620","0621","0622","0623","0624","0625","0626","0627","0628","0629","0630","0631","0632","0633","0634","0635","0636","0637","0638","0639","0640","0641","0642","0643","0644","0645","0646","0647","0648","0649",
"0650","0651","0652","0653","0654","0655","0656","0657","0658","0659","0660","0661","0662","0663","0664","0665","0666","0667","0668","0669","0670","0671","0672","0673","0674","0675","0676","0677","0678","0679","0680","0681","0682","0683","0684","0685","0686","0687","0688","0689","0690","0691","0692","0693","0694","0695","0696","0697","0698","0699",
"0700","0701","0702","0703","0704","0705","0706","0707","0708","0709","0710","0711","0712","0713","0714","0715","0716","0717","0718","0719","0720","0721","0722","0723","0724","0725","0726","0727","0728","0729","0730","0731","0732","0733","0734","0735","0736","0737","0738","0739","0740","0741","0742","0743","0744","0745","0746","0747","0748","0749",
"0750","0751","0752","0753","0754","0755","0756","0757","0758","0759","0760","0761","0762","0763","0764","0765","0766","0767","0768","0769","0770","0771","0772","0773","0774","0775","0776","0777","0778","0779","0780","0781","0782","0783","0784","0785","0786","0787","0788","0789","0790","0791","0792","0793","0794","0795","0796","0797","0798","0799",
"0800","0801","0802","0803","0804","0805","0806","0807","0808","0809","0810","0811","0812","0813","0814","0815","0816","0817","0818","0819","0820","0821","0822","0823","0824","0825","0826","0827","0828","0829","0830","0831","0832","0833","0834","0835","0836","0837","0838","0839","0840","0841","0842","0843","0844","0845","0846","0847","0848","0849",
"0850","0851","0852","0853","0854","0855","0856","0857","0858","0859","0860","0861","0862","0863","0864","0865","0866","0867","0868","0869","0870","0871","0872","0873","0874","0875","0876","0877","0878","0879","0880","0881","0882","0883","0884","0885","0886","0887","0888","0889","0890","0891","0892","0893","0894","0895","0896","0897","0898","0899",
"0900","0901","0902","0903","0904","0905","0906","0907","0908","0909","0910","0911","0912","0913","0914","0915","0916","0917","0918","0919","0920","0921","0922","0923","0924","0925","0926","0927","0928","0929","0930","0931","0932","0933","0934","0935","0936","0937","0938","0939","0940","0941","0942","0943","0944","0945","0946","0947","0948","0949",
"0950","0951","0952","0953","0954","0955","0956","0957","0958","0959","0960","0961","0962","0963","0964","0965","0966","0967","0968","0969","0970","0971","0972","0973","0974","0975","0976","0977","0978","0979","0980","0981","0982","0983","0984","0985","0986","0987","0988","0989","0990","0991","0992","0993","0994","0995","0996","0997","0998","0999",
"1000","1001","1002","1003","1004","1005","1006","1007","1008","1009","1010","1011","1012","1013","1014","1015","1016","1017","1018","1019","1020","1021","1022","1023","1024","1025","1026","1027","1028","1029","1030","1031","1032","1033","1034","1035","1036","1037","1038","1039","1040","1041","1042","1043","1044","1045","1046","1047","1048","1049",
"1050","1051","1052","1053","1054","1055","1056","1057","1058","1059","1060","1061","1062","1063","1064","1065","1066","1067","1068","1069","1070","1071","1072","1073","1074","1075","1076","1077","1078","1079","1080","1081","1082","1083","1084","1085","1086","1087","1088","1089","1090","1091","1092","1093","1094","1095","1096","1097","1098","1099",
"1100","1101","1102","1103","1104","1105","1106","1107","1108","1109","1110","1111","1112","1113","1114","1115","1116","1117","1118","1119","1120","1121","1122","1123","1124","1125","1126","1127","1128","1129","1130","1131","1132","1133","1134","1135","1136","1137","1138","1139","1140","1141","1142","1143","1144","1145","1146","1147","1148","1149",
"1150","1151","1152","1153","1154","1155","1156","1157","1158","1159","1160","1161","1162","1163","1164","1165","1166","1167","1168","1169","1170","1171","1172","1173","1174","1175","1176","1177","1178","1179","1180","1181","1182","1183","1184","1185","1186","1187","1188","1189","1190","1191","1192","1193","1194","1195","1196","1197","1198","1199",
"1200","1201","1202","1203","1204","1205","1206","1207","1208","1209","1210","1211","1212","1213","1214","1215","1216","1217","1218","1219","1220","1221","1222","1223","1224","1225","1226","1227","1228","1229","1230","1231","1232","1233","1234","1235","1236","1237","1238","1239","1240","1241","1242","1243","1244","1245","1246","1247","1248","1249",
"1250","1251","1252","1253","1254","1255","1256","1257","1258","1259","1260","1261","1262","1263","1264","1265","1266","1267","1268","1269","1270","1271","1272","1273","1274","1275","1276","1277","1278","1279","1280","1281","1282","1283","1284","1285","1286","1287","1288","1289","1290","1291","1292","1293","1294","1295","1296","1297","1298","1299",
"1300","1301","1302","1303","1304","1305","1306","1307","1308","1309","1310","1311","1312","1313","1314","1315","1316","1317","1318","1319","1320","1321","1322","1323","1324","1325","1326","1327","1328","1329","1330","1331","1332","1333","1334","1335","1336","1337","1338","1339","1340","1341","1342","1343","1344","1345","1346","1347","1348","1349",
"1350","1351","1352","1353","1354","1355","1356","1357","1358","1359","1360","1361","1362","1363","1364","1365","1366","1367","1368","1369","1370","1371","1372","1373","1374","1375","1376","1377","1378","1379","1380","1381","1382","1383","1384","1385","1386","1387","1388","1389","1390","1391","1392","1393","1394","1395","1396","1397","1398","1399",
"1400","1401","1402","1403","1404","1405","1406","1407","1408","1409","1410","1411","1412","1413","1414","1415","1416","1417","1418","1419","1420","1421","1422","1423","1424","1425","1426","1427","1428","1429","1430","1431","1432","1433","1434","1435","1436","1437","1438","1439","1440","1441","1442","1443","1444","1445","1446","1447","1448","1449",
"1450","1451","1452","1453","1454","1455","1456","1457","1458","1459","1460","1461","1462","1463","1464","1465","1466","1467","1468","1469","1470","1471","1472","1473","1474","1475","1476","1477","1478","1479","1480","1481","1482","1483","1484","1485","1486","1487","1488","1489","1490","1491","1492","1493","1494","1495","1496","1497","1498","1499",
"1500","1501","1502","1503","1504","1505","1506","1507","1508","1509","1510","1511","1512","1513","1514","1515","1516","1517","1518","1519","1520","1521","1522","1523","1524","1525","1526","1527","1528","1529","1530","1531","1532","1533","1534","1535","1536","1537","1538","1539","1540","1541","1542","1543","1544","1545","1546","1547","1548","1549",
"1550","1551","1552","1553","1554","1555","1556","1557","1558","1559","1560","1561","1562","1563","1564","1565","1566","1567","1568","1569","1570","1571","1572","1573","1574","1575","1576","1577","1578","1579","1580","1581","1582","1583","1584","1585","1586","1587","1588","1589","1590","1591","1592","1593","1594","1595","1596","1597","1598","1599",
"1600","1601","1602","1603","1604","1605","1606","1607","1608","1609","1610","1611","1612","1613","1614","1615","1616","1617","1618","1619","1620","1621","1622","1623","1624","1625","1626","1627","1628","1629","1630","1631","1632","1633","1634","1635","1636","1637","1638","1639","1640","1641","1642","1643","1644","1645","1646","1647","1648","1649",
"1650","1651","1652","1653","1654","1655","1656","1657","1658","1659","1660","1661","1662","1663","1664","1665","1666","1667","1668","1669","1670","1671","1672","1673","1674","1675","1676","1677","1678","1679","1680","1681","1682","1683","1684","1685","1686","1687","1688","1689","1690","1691","1692","1693","1694","1695","1696","1697","1698","1699",
"1700","1701","1702","1703","1704","1705","1706","1707","1708","1709","1710","1711","1712","1713","1714","1715","1716","1717","1718","1719","1720","1721","1722","1723","1724","1725","1726","1727","1728","1729","1730","1731","1732","1733","1734","1735","1736","1737","1738","1739","1740","1741","1742","1743","1744","1745","1746","1747","1748","1749",
"1750","1751","1752","1753","1754","1755","1756","1757","1758","1759","1760","1761","1762","1763","1764","1765","1766","1767","1768","1769","1770","1771","1772","1773","1774","1775","1776","1777","1778","1779","1780","1781","1782","1783","1784","1785","1786","1787","1788","1789","1790","1791","1792","1793","1794","1795","1796","1797","1798","1799",
"1800","1801","1802","1803","1804","1805","1806","1807","1808","1809","1810","1811","1812","1813","1814","1815","1816","1817","1818","1819","1820","1821","1822","1823","1824","1825","1826","1827","1828","1829","1830","1831","1832","1833","1834","1835","1836","1837","1838","1839","1840","1841","1842","1843","1844","1845","1846","1847","1848","1849",
"1850","1851","1852","1853","1854","1855","1856","1857","1858","1859","1860","1861","1862","1863","1864","1865","1866","1867","1868","1869","1870","1871","1872","1873","1874","1875","1876","1877","1878","1879","1880","1881","1882","1883","1884","1885","1886","1887","1888","1889","1890","1891","1892","1893","1894","1895","1896","1897","1898","1899",
"1900","1901","1902","1903","1904","1905","1906","1907","1908","1909","1910","1911","1912","1913","1914","1915","1916","1917","1918","1919","1920","1921","1922","1923","1924","1925","1926","1927","1928","1929","1930","1931","1932","1933","1934","1935","1936","1937","1938","1939","1940","1941","1942","1943","1944","1945","1946","1947","1948","1949",
"1950","1951","1952","1953","1954","1955","1956","1957","1958","1959","1960","1961","1962","1963","1964","1965","1966","1967","1968","1969","1970","1971","1972","1973","1974","1975","1976","1977","1978","1979","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999",
"2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018","2019","2020","2021","2022","2023","2024","2025","2026","2027","2028","2029","2030","2031","2032","2033","2034","2035","2036","2037","2038","2039","2040","2041","2042","2043","2044","2045","2046","2047","2048","2049",
"2050","2051","2052","2053","2054","2055","2056","2057","2058","2059","2060","2061","2062","2063","2064","2065","2066","2067","2068","2069","2070","2071","2072","2073","2074","2075","2076","2077","2078","2079","2080","2081","2082","2083","2084","2085","2086","2087","2088","2089","2090","2091","2092","2093","2094","2095","2096","2097","2098","2099",
"2100","2101","2102","2103","2104","2105","2106","2107","2108","2109","2110","2111","2112","2113","2114","2115","2116","2117","2118","2119","2120","2121","2122","2123","2124","2125","2126","2127","2128","2129","2130","2131","2132","2133","2134","2135","2136","2137","2138","2139","2140","2141","2142","2143","2144","2145","2146","2147","2148","2149",
"2150","2151","2152","2153","2154","2155","2156","2157","2158","2159","2160","2161","2162","2163","2164","2165","2166","2167","2168","2169","2170","2171","2172","2173","2174","2175","2176","2177","2178","2179","2180","2181","2182","2183","2184","2185","2186","2187","2188","2189","2190","2191","2192","2193","2194","2195","2196","2197","2198","2199",
"2200","2201","2202","2203","2204","2205","2206","2207","2208","2209","2210","2211","2212","2213","2214","2215","2216","2217","2218","2219","2220","2221","2222","2223","2224","2225","2226","2227","2228","2229","2230","2231","2232","2233","2234","2235","2236","2237","2238","2239","2240","2241","2242","2243","2244","2245","2246","2247","2248","2249",
"2250","2251","2252","2253","2254","2255","2256","2257","2258","2259","2260","2261","2262","2263","2264","2265","2266","2267","2268","2269","2270","2271","2272","2273","2274","2275","2276","2277","2278","2279","2280","2281","2282","2283","2284","2285","2286","2287","2288","2289","2290","2291","2292","2293","2294","2295","2296","2297","2298","2299",
"2300","2301","2302","2303","2304","2305","2306","2307","2308","2309","2310","2311","2312","2313","2314","2315","2316","2317","2318","2319","2320","2321","2322","2323","2324","2325","2326","2327","2328","2329","2330","2331","2332","2333","2334","2335","2336","2337","2338","2339","2340","2341","2342","2343","2344","2345","2346","2347","2348","2349",
"2350","2351","2352","2353","2354","2355","2356","2357","2358","2359","2360","2361","2362","2363","2364","2365","2366","2367","2368","2369","2370","2371","2372","2373","2374","2375","2376","2377","2378","2379","2380","2381","2382","2383","2384","2385","2386","2387","2388","2389","2390","2391","2392","2393","2394","2395","2396","2397","2398","2399",
"2400","2401","2402","2403","2404","2405","2406","2407","2408","2409","2410","2411","2412","2413","2414","2415","2416","2417","2418","2419","2420","2421","2422","2423","2424","2425","2426","2427","2428","2429","2430","2431","2432","2433","2434","2435","2436","2437","2438","2439","2440","2441","2442","2443","2444","2445","2446","2447","2448","2449",
"2450","2451","2452","2453","2454","2455","2456","2457","2458","2459","2460","2461","2462","2463","2464","2465","2466","2467","2468","2469","2470","2471","2472","2473","2474","2475","2476","2477","2478","2479","2480","2481","2482","2483","2484","2485","2486","2487","2488","2489","2490","2491","2492","2493","2494","2495","2496","2497","2498","2499",
"2500","2501","2502","2503","2504","2505","2506","2507","2508","2509","2510","2511","2512","2513","2514","2515","2516","2517","2518","2519","2520","2521","2522","2523","2524","2525","2526","2527","2528","2529","2530","2531","2532","2533","2534","2535","2536","2537","2538","2539","2540","2541","2542","2543","2544","2545","2546","2547","2548","2549",
"2550","2551","2552","2553","2554","2555","2556","2557","2558","2559","2560","2561","2562","2563","2564","2565","2566","2567","2568","2569","2570","2571","2572","2573","2574","2575","2576","2577","2578","2579","2580","2581","2582","2583","2584","2585","2586","2587","2588","2589","2590","2591","2592","2593","2594","2595","2596","2597","2598","2599",
"2600","2601","2602","2603","2604","2605","2606","2607","2608","2609","2610","2611","2612","2613","2614","2615","2616","2617","2618","2619","2620","2621","2622","2623","2624","2625","2626","2627","2628","2629","2630","2631","2632","2633","2634","2635","2636","2637","2638","2639","2640","2641","2642","2643","2644","2645","2646","2647","2648","2649",
"2650","2651","2652","2653","2654","2655","2656","2657","2658","2659","2660","2661","2662","2663","2664","2665","2666","2667","2668","2669","2670","2671","2672","2673","2674","2675","2676","2677","2678","2679","2680","2681","2682","2683","2684","2685","2686","2687","2688","2689","2690","2691","2692","2693","2694","2695","2696","2697","2698","2699",
"2700","2701","2702","2703","2704","2705","2706","2707","2708","2709","2710","2711","2712","2713","2714","2715","2716","2717","2718","2719","2720","2721","2722","2723","2724","2725","2726","2727","2728","2729","2730","2731","2732","2733","2734","2735","2736","2737","2738","2739","2740","2741","2742","2743","2744","2745","2746","2747","2748","2749",
"2750","2751","2752","2753","2754","2755","2756","2757","2758","2759","2760","2761","2762","2763","2764","2765","2766","2767","2768","2769","2770","2771","2772","2773","2774","2775","2776","2777","2778","2779","2780","2781","2782","2783","2784","2785","2786","2787","2788","2789","2790","2791","2792","2793","2794","2795","2796","2797","2798","2799",
"2800","2801","2802","2803","2804","2805","2806","2807","2808","2809","2810","2811","2812","2813","2814","2815","2816","2817","2818","2819","2820","2821","2822","2823","2824","2825","2826","2827","2828","2829","2830","2831","2832","2833","2834","2835","2836","2837","2838","2839","2840","2841","2842","2843","2844","2845","2846","2847","2848","2849",
"2850","2851","2852","2853","2854","2855","2856","2857","2858","2859","2860","2861","2862","2863","2864","2865","2866","2867","2868","2869","2870","2871","2872","2873","2874","2875","2876","2877","2878","2879","2880","2881","2882","2883","2884","2885","2886","2887","2888","2889","2890","2891","2892","2893","2894","2895","2896","2897","2898","2899",
"2900","2901","2902","2903","2904","2905","2906","2907","2908","2909","2910","2911","2912","2913","2914","2915","2916","2917","2918","2919","2920","2921","2922","2923","2924","2925","2926","2927","2928","2929","2930","2931","2932","2933","2934","2935","2936","2937","2938","2939","2940","2941","2942","2943","2944","2945","2946","2947","2948","2949",
"2950","2951","2952","2953","2954","2955","2956","2957","2958","2959","2960","2961","2962","2963","2964","2965","2966","2967","2968","2969","2970","2971","2972","2973","2974","2975","2976","2977","2978","2979","2980","2981","2982","2983","2984","2985","2986","2987","2988","2989","2990","2991","2992","2993","2994","2995","2996","2997","2998","2999",
"3000","3001","3002","3003","3004","3005","3006","3007","3008","3009","3010","3011","3012","3013","3014","3015","3016","3017","3018","3019","3020","3021","3022","3023","3024","3025","3026","3027","3028","3029","3030","3031","3032","3033","3034","3035","3036","3037","3038","3039","3040","3041","3042","3043","3044","3045","3046","3047","3048","3049",
"3050","3051","3052","3053","3054","3055","3056","3057","3058","3059","3060","3061","3062","3063","3064","3065","3066","3067","3068","3069","3070","3071","3072","3073","3074","3075","3076","3077","3078","3079","3080","3081","3082","3083","3084","3085","3086","3087","3088","3089","3090","3091","3092","3093","3094","3095","3096","3097","3098","3099",
"3100","3101","3102","3103","3104","3105","3106","3107","3108","3109","3110","3111","3112","3113","3114","3115","3116","3117","3118","3119","3120","3121","3122","3123","3124","3125","3126","3127","3128","3129","3130","3131","3132","3133","3134","3135","3136","3137","3138","3139","3140","3141","3142","3143","3144","3145","3146","3147","3148","3149",
"3150","3151","3152","3153","3154","3155","3156","3157","3158","3159","3160","3161","3162","3163","3164","3165","3166","3167","3168","3169","3170","3171","3172","3173","3174","3175","3176","3177","3178","3179","3180","3181","3182","3183","3184","3185","3186","3187","3188","3189","3190","3191","3192","3193","3194","3195","3196","3197","3198","3199",
"3200","3201","3202","3203","3204","3205","3206","3207","3208","3209","3210","3211","3212","3213","3214","3215","3216","3217","3218","3219","3220","3221","3222","3223","3224","3225","3226","3227","3228","3229","3230","3231","3232","3233","3234","3235","3236","3237","3238","3239","3240","3241","3242","3243","3244","3245","3246","3247","3248","3249",
"3250","3251","3252","3253","3254","3255","3256","3257","3258","3259","3260","3261","3262","3263","3264","3265","3266","3267","3268","3269","3270","3271","3272","3273","3274","3275","3276","3277","3278","3279","3280","3281","3282","3283","3284","3285","3286","3287","3288","3289","3290","3291","3292","3293","3294","3295","3296","3297","3298","3299",
"3300","3301","3302","3303","3304","3305","3306","3307","3308","3309","3310","3311","3312","3313","3314","3315","3316","3317","3318","3319","3320","3321","3322","3323","3324","3325","3326","3327","3328","3329","3330","3331","3332","3333","3334","3335","3336","3337","3338","3339","3340","3341","3342","3343","3344","3345","3346","3347","3348","3349",
"3350","3351","3352","3353","3354","3355","3356","3357","3358","3359","3360","3361","3362","3363","3364","3365","3366","3367","3368","3369","3370","3371","3372","3373","3374","3375","3376","3377","3378","3379","3380","3381","3382","3383","3384","3385","3386","3387","3388","3389","3390","3391","3392","3393","3394","3395","3396","3397","3398","3399",
"3400","3401","3402","3403","3404","3405","3406","3407","3408","3409","3410","3411","3412","3413","3414","3415","3416","3417","3418","3419","3420","3421","3422","3423","3424","3425","3426","3427","3428","3429","3430","3431","3432","3433","3434","3435","3436","3437","3438","3439","3440","3441","3442","3443","3444","3445","3446","3447","3448","3449",
"3450","3451","3452","3453","3454","3455","3456","3457","3458","3459","3460","3461","3462","3463","3464","3465","3466","3467","3468","3469","3470","3471","3472","3473","3474","3475","3476","3477","3478","3479","3480","3481","3482","3483","3484","3485","3486","3487","3488","3489","3490","3491","3492","3493","3494","3495","3496","3497","3498","3499",
"3500","3501","3502","3503","3504","3505","3506","3507","3508","3509","3510","3511","3512","3513","3514","3515","3516","3517","3518","3519","3520","3521","3522","3523","3524","3525","3526","3527","3528","3529","3530","3531","3532","3533","3534","3535","3536","3537","3538","3539","3540","3541","3542","3543","3544","3545","3546","3547","3548","3549",
"3550","3551","3552","3553","3554","3555","3556","3557","3558","3559","3560","3561","3562","3563","3564","3565","3566","3567","3568","3569","3570","3571","3572","3573","3574","3575","3576","3577","3578","3579","3580","3581","3582","3583","3584","3585","3586","3587","3588","3589","3590","3591","3592","3593","3594","3595","3596","3597","3598","3599",
"3600","3601","3602","3603","3604","3605","3606","3607","3608","3609","3610","3611","3612","3613","3614","3615","3616","3617","3618","3619","3620","3621","3622","3623","3624","3625","3626","3627","3628","3629","3630","3631","3632","3633","3634","3635","3636","3637","3638","3639","3640","3641","3642","3643","3644","3645","3646","3647","3648","3649",
"3650","3651","3652","3653","3654","3655","3656","3657","3658","3659","3660","3661","3662","3663","3664","3665","3666","3667","3668","3669","3670","3671","3672","3673","3674","3675","3676","3677","3678","3679","3680","3681","3682","3683","3684","3685","3686","3687","3688","3689","3690","3691","3692","3693","3694","3695","3696","3697","3698","3699",
"3700","3701","3702","3703","3704","3705","3706","3707","3708","3709","3710","3711","3712","3713","3714","3715","3716","3717","3718","3719","3720","3721","3722","3723","3724","3725","3726","3727","3728","3729","3730","3731","3732","3733","3734","3735","3736","3737","3738","3739","3740","3741","3742","3743","3744","3745","3746","3747","3748","3749",
"3750","3751","3752","3753","3754","3755","3756","3757","3758","3759","3760","3761","3762","3763","3764","3765","3766","3767","3768","3769","3770","3771","3772","3773","3774","3775","3776","3777","3778","3779","3780","3781","3782","3783","3784","3785","3786","3787","3788","3789","3790","3791","3792","3793","3794","3795","3796","3797","3798","3799",
"3800","3801","3802","3803","3804","3805","3806","3807","3808","3809","3810","3811","3812","3813","3814","3815","3816","3817","3818","3819","3820","3821","3822","3823","3824","3825","3826","3827","3828","3829","3830","3831","3832","3833","3834","3835","3836","3837","3838","3839","3840","3841","3842","3843","3844","3845","3846","3847","3848","3849",
"3850","3851","3852","3853","3854","3855","3856","3857","3858","3859","3860","3861","3862","3863","3864","3865","3866","3867","3868","3869","3870","3871","3872","3873","3874","3875","3876","3877","3878","3879","3880","3881","3882","3883","3884","3885","3886","3887","3888","3889","3890","3891","3892","3893","3894","3895","3896","3897","3898","3899",
"3900","3901","3902","3903","3904","3905","3906","3907","3908","3909","3910","3911","3912","3913","3914","3915","3916","3917","3918","3919","3920","3921","3922","3923","3924","3925","3926","3927","3928","3929","3930","3931","3932","3933","3934","3935","3936","3937","3938","3939","3940","3941","3942","3943","3944","3945","3946","3947","3948","3949",
"3950","3951","3952","3953","3954","3955","3956","3957","3958","3959","3960","3961","3962","3963","3964","3965","3966","3967","3968","3969","3970","3971","3972","3973","3974","3975","3976","3977","3978","3979","3980","3981","3982","3983","3984","3985","3986","3987","3988","3989","3990","3991","3992","3993","3994","3995","3996","3997","3998","3999" };




localparam  DDR3_WDQ_PHASE_pss = Altera_Dummy_String[DDR3_WDQ_PHASE_ps] ;
localparam  DDR3_RDQ_PHASE_pss = Altera_Dummy_String[DDR3_RDQ_PHASE_ps] ;

// Altera did it again.  Another string which cannot be expressed as a string.
// Another workaround of mine which looks utterly stupid, but the only possible way to get it to function.

localparam FPGA_FAMILY_string = (FPGA_FAMILY=="Arria II GX")   ? "Arria II GX"   :
                                (FPGA_FAMILY=="Cyclone III")   ? "Cyclone III"   :
                                (FPGA_FAMILY=="Cyclone IV E")  ? "Cyclone IV E"  :
                                (FPGA_FAMILY=="Cyclone V")     ? "Cyclone V"     :
                                (FPGA_FAMILY=="MAX 10")        ? "MAX 10"        :
                                (FPGA_FAMILY=="Cyclone 10 LP") ? "Cyclone 10 LP" :
                                                                 "MAX 10"          ;

wire [4:0]  PLL1_clk_out;    // PLL has 5 outputs.

generate
// ******************************************************************************************************************************************
// ***  ALTERA/INTEL PLL ********************************************************************************************************************
// ******************************************************************************************************************************************
if (FPGA_VENDOR[0] == "A" || FPGA_VENDOR[0] == "a" || FPGA_VENDOR[0] == "I" || FPGA_VENDOR[0] == "i") begin 

// ****************************************************************************************
// *** Begin Initiate DDR3 clock Altera PLL for Cyclone III/IV/10LP/MAX 10/Arria II  ******
// ****************************************************************************************

if (FPGA_FAMILY!="Cyclone V") begin
 altpll #(

  .bandwidth_type ("AUTO"),           .inclk0_input_frequency (PLL1_inps),  .compensate_clock ("CLK0"),         .lpm_hint ("CBX_MODULE_PREFIX=BrianHG_DDR3_PLL"),
  .clk0_divide_by (CLK_IN_DIV),       .clk0_duty_cycle (50),                .clk0_multiply_by (CLK_IN_MULT),    .clk0_phase_shift ("0"),
  .clk1_divide_by (CLK_IN_DIV),       .clk1_duty_cycle (50),                .clk1_multiply_by (CLK_IN_MULT),    .clk1_phase_shift (DDR3_WDQ_PHASE_pss),
  .clk2_divide_by (CLK_IN_DIV),       .clk2_duty_cycle (50),                .clk2_multiply_by (CLK_IN_MULT),    .clk2_phase_shift (DDR3_RDQ_PHASE_pss),
  .clk3_divide_by (CLK_IN_DIV*2),     .clk3_duty_cycle (50),                .clk3_multiply_by (CLK_IN_MULT),    .clk3_phase_shift ("0"),
  .clk4_divide_by (CLK_IN_DIV*4),     .clk4_duty_cycle (50),                .clk4_multiply_by (CLK_IN_MULT),    .clk4_phase_shift ("0"),

  .lpm_type         ("altpll"),       .operation_mode    ("NORMAL"),        .pll_type         ("AUTO"),         .port_activeclock        ("PORT_UNUSED"),
  .port_areset      ("PORT_USED"),    .port_clkbad0      ("PORT_UNUSED"),   .port_clkbad1     ("PORT_UNUSED"),  .port_clkloss            ("PORT_UNUSED"),
  .port_clkswitch   ("PORT_UNUSED"),  .port_configupdate ("PORT_UNUSED"),   .port_fbin        ("PORT_UNUSED"),  .port_inclk0             ("PORT_USED"),
  .port_inclk1      ("PORT_UNUSED"),  .port_locked       ("PORT_USED"),     .port_pfdena      ("PORT_UNUSED"),  .port_phasecounterselect ("PORT_USED"),
  .port_phasedone   ("PORT_USED"),    .port_phasestep    ("PORT_USED"),     .port_phaseupdown ("PORT_USED"),    .port_pllena             ("PORT_UNUSED"),
  .port_scanaclr    ("PORT_UNUSED"),  .port_scanclk      ("PORT_USED"),     .port_scanclkena  ("PORT_UNUSED"),  .port_scandata           ("PORT_UNUSED"),
  .port_scandataout ("PORT_UNUSED"),  .port_scandone     ("PORT_UNUSED"),   .port_scanread    ("PORT_UNUSED"),  .port_scanwrite          ("PORT_UNUSED"),
  .port_clk0        ("PORT_USED"),    .port_clk1         ("PORT_USED"),     .port_clk2        ("PORT_USED"),    .port_clk3               ("PORT_USED"),
  .port_clk4        ("PORT_USED"),    .port_clk5         ("PORT_UNUSED"),   .port_clkena0     ("PORT_UNUSED"),  .port_clkena1            ("PORT_UNUSED"),
  .port_clkena2     ("PORT_UNUSED"),  .port_clkena3      ("PORT_UNUSED"),   .port_clkena4     ("PORT_UNUSED"),  .port_clkena5            ("PORT_UNUSED"),
  .port_extclk0     ("PORT_UNUSED"),  .port_extclk1      ("PORT_UNUSED"),   .port_extclk2     ("PORT_UNUSED"),  .port_extclk3            ("PORT_UNUSED"),
  .width_clock      (5),              .width_phasecounterselect (3),        .self_reset_on_loss_lock ("OFF"),   .intended_device_family  (FPGA_FAMILY_string)

 ) DDR3_PLL5 (
                .inclk ({1'b0, CLK_IN}),   .clk (PLL1_clk_out),
                .activeclock (),           .areset (RST_PLL),      .clkbad (),          .clkena ({6{1'b1}}),     .clkloss (),
                .clkswitch (1'b0),         .configupdate (1'b0),   .enable0 (),         .enable1 (),             .extclk (),
                .extclkena ({4{1'b1}}),    .fbin (1'b1),           .fbmimicbidir (),    .fbout (),               .fref (),
                .icdrclk (),               .locked (PLL_LOCKED),   .pfdena (1'b1),      .phasedone (phase_done), .phasestep (phase_step),
                .phaseupdown (phase_updn), .pllena (1'b1),         .scanaclr (1'b0),    .scanclk (phase_sclk),   .scanclkena (1'b1),
                .scandata (1'b0),          .scandataout (),        .scandone (),        .scanread (1'b0),        .scanwrite (1'b0),
                .sclkout0 (),              .sclkout1 (),           .vcooverrange (),    .vcounderrange (),       .phasecounterselect (3'd4));

end else begin

// ***********************************************************************************************
// ***********************************************************************************************
// ***********************************************************************************************
// ********************** Cyclone V, Arria V, Stratix V Style PLL ********************************
// ***********************************************************************************************
// ***********************************************************************************************
// ***********************************************************************************************


// ***************************************************************
// ***  Cyclone V does not support DDR_TRICK_MTPS_CAP ************
// ***************************************************************
if (DDR_TRICK_MTPS_CAP != 0 )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("***************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .DDR_TRICK_MTPS_CAP must be  ***");
$warning("*** set to 0 when using a Cyclone V PLL.                    ***");
$warning("***************************************************************");
$error;
$stop;
end

localparam  C100 = (PLL1_OUT_TRUE_KHZ==600000) ? "600.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==575000) ? "575.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==550000) ? "550.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==525000) ? "525.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==500000) ? "500.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==475000) ? "475.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==450000) ? "450.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==425000) ? "425.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==400000) ? "400.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==375000) ? "375.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==350000) ? "350.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==325000) ? "325.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==300000) ? "300.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==275000) ? "275.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==250000) ? "250.000000 MHz" : 0 ;

localparam  C101 = (PLL1_OUT_TRUE_KHZ==600000) ? "600.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==575000) ? "575.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==550000) ? "550.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==525000) ? "525.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==500000) ? "500.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==475000) ? "475.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==450000) ? "450.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==425000) ? "425.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==400000) ? "400.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==375000) ? "375.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==350000) ? "350.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==325000) ? "325.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==300000) ? "300.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==275000) ? "275.000001 MHz" :
                   (PLL1_OUT_TRUE_KHZ==250000) ? "250.000001 MHz" : 0 ;

localparam  C050 = (PLL1_OUT_TRUE_KHZ==600000) ? "300.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==575000) ? "287.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==550000) ? "275.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==525000) ? "262.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==500000) ? "250.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==475000) ? "237.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==450000) ? "225.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==425000) ? "212.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==400000) ? "200.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==375000) ? "187.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==350000) ? "175.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==325000) ? "162.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==300000) ? "150.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==275000) ? "137.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==250000) ? "125.000000 MHz" : 0 ;

localparam  C025 = (PLL1_OUT_TRUE_KHZ==600000) ? "150.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==575000) ? "143.750000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==550000) ? "137.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==525000) ? "131.250000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==500000) ? "125.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==475000) ? "118.750000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==450000) ? "112.500000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==425000) ? "106.250000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==400000) ? "100.000000 MHz" :
                   (PLL1_OUT_TRUE_KHZ==375000) ? "93.750000 MHz"  :
                   (PLL1_OUT_TRUE_KHZ==350000) ? "87.500000 MHz"  :
                   (PLL1_OUT_TRUE_KHZ==325000) ? "81.250000 MHz"  :
                   (PLL1_OUT_TRUE_KHZ==300000) ? "75.000000 MHz"  :
                   (PLL1_OUT_TRUE_KHZ==275000) ? "68.750000 MHz"  :
                   (PLL1_OUT_TRUE_KHZ==250000) ? "62.500000 MHz"  : 0 ;

// ****************************************************
// ***  Unknown Cyclone V output frequency ************
// ****************************************************
if (C100 == 0 )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("************************************************************************************");
$warning("*** BrianHG_DDR3_PLL Cyclone V output frequency %d MHz is not supported.       ***",12'(PLL1_OUT_TRUE_KHZ/1000));
$warning("*** Please change the .CLK_IN_MULT and .CLK_IN_DIV parameters so that the output ***");
$warning("*** frequency is 250, 275, 300, 325, 350, 375, 400, 425, 450, 475 or 500 MHz.    ***");
$warning("************************************************************************************");
$error;
$stop;
end

localparam W_CPMP = (DDR3_WDQ_PHASE==0  ) ? 0 :
                    (DDR3_WDQ_PHASE==45 ) ? 1 :
                    (DDR3_WDQ_PHASE==90 ) ? 2 :
                    (DDR3_WDQ_PHASE==135) ? 3 :
                    (DDR3_WDQ_PHASE==180) ? 4 :
                    (DDR3_WDQ_PHASE==225) ? 5 :
                    (DDR3_WDQ_PHASE==270) ? 6 :
                    (DDR3_WDQ_PHASE==315) ? 7 : 8 ;

if (W_CPMP == 8 )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("**************************************************************************");
$warning("*** BrianHG_DDR3_PLL Cyclone V .DDR3_WDQ_PHASE(%d) is not supported. ***",10'(DDR3_WDQ_PHASE));
$warning("*** Only 0, 45, 90, 135, 180, 225, 270, 315 deg. are allowed.          ***");
$warning("**************************************************************************");
$error;
$stop;
end

if (DDR3_RDQ_PHASE != 0 )  initial begin
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("**************************************************************************");
$warning("*** BrianHG_DDR3_PLL Cyclone V .DDR3_RDQ_PHASE(%d) is not supported. ***",10'(DDR3_RDQ_PHASE));
$warning("*** Only 0 deg. is allowed.                                            ***");
$warning("**************************************************************************");
$error;
$stop;
end

altera_pll #(
  .fractional_vco_multiplier ("false"),          .reference_clock_frequency  (RCF),            .pll_fractional_cout  (32),
  .pll_dsm_out_sel           ("disable"),        .operation_mode             ("normal"),       .number_of_clocks     (5),

  .output_clock_frequency0  (C100),              .phase_shift0  ("0 ps"),              .duty_cycle0  (50),
  .output_clock_frequency1  (C100),              .phase_shift1  (DDR3_WDQ_PHASE_pss),  .duty_cycle1  (50),  //1875-400  2500-300
  .output_clock_frequency2  (C101),              .phase_shift2  ("0 ps"),              .duty_cycle2  (50),  // Come on Altera, If I don't place this 0.000001 MHz offset, you remove this clock from my design.
  .output_clock_frequency3  (C050),              .phase_shift3  ("0 ps"),              .duty_cycle3  (50),
  .output_clock_frequency4  (C025),              .phase_shift4  ("0 ps"),              .duty_cycle4  (50),
  .output_clock_frequency5  ("0 MHz"),           .phase_shift5  ("0 ps"),              .duty_cycle5  (50),
  .output_clock_frequency6  ("0 MHz"),           .phase_shift6  ("0 ps"),              .duty_cycle6  (50),
  .output_clock_frequency7  ("0 MHz"),           .phase_shift7  ("0 ps"),              .duty_cycle7  (50),
  .output_clock_frequency8  ("0 MHz"),           .phase_shift8  ("0 ps"),              .duty_cycle8  (50),
  .output_clock_frequency9  ("0 MHz"),           .phase_shift9  ("0 ps"),              .duty_cycle9  (50),
  .output_clock_frequency10 ("0 MHz"),           .phase_shift10 ("0 ps"),              .duty_cycle10 (50),
  .output_clock_frequency11 ("0 MHz"),           .phase_shift11 ("0 ps"),              .duty_cycle11 (50),
  .output_clock_frequency12 ("0 MHz"),           .phase_shift12 ("0 ps"),              .duty_cycle12 (50),
  .output_clock_frequency13 ("0 MHz"),           .phase_shift13 ("0 ps"),              .duty_cycle13 (50),
  .output_clock_frequency14 ("0 MHz"),           .phase_shift14 ("0 ps"),              .duty_cycle14 (50),
  .output_clock_frequency15 ("0 MHz"),           .phase_shift15 ("0 ps"),              .duty_cycle15 (50),
  .output_clock_frequency16 ("0 MHz"),           .phase_shift16 ("0 ps"),              .duty_cycle16 (50),
  .output_clock_frequency17 ("0 MHz"),           .phase_shift17 ("0 ps"),              .duty_cycle17 (50),

  .pll_type        (FPGA_FAMILY_string),                            .pll_subtype           ("DPS"),

  .m_cnt_hi_div    (CLK_IN_MULT/2),  .m_cnt_lo_div    (CLK_IN_MULT/2),  .n_cnt_hi_div          (CLK_IN_DIV/2),   .n_cnt_lo_div          (CLK_IN_DIV/2),
  .m_cnt_bypass_en ("false"),        .n_cnt_bypass_en ("false"),        .m_cnt_odd_div_duty_en ("false"),        .n_cnt_odd_div_duty_en ("false"),

  .c_cnt_hi_div0  (256),  .c_cnt_lo_div0  (256),  .c_cnt_prst0  (1),    .c_cnt_ph_mux_prst0  (0),      .c_cnt_in_src0  ("ph_mux_clk"),  .c_cnt_bypass_en0  ("true"),   .c_cnt_odd_div_duty_en0  ("false"),
  .c_cnt_hi_div1  (256),  .c_cnt_lo_div1  (256),  .c_cnt_prst1  (1),    .c_cnt_ph_mux_prst1  (W_CPMP), .c_cnt_in_src1  ("ph_mux_clk"),  .c_cnt_bypass_en1  ("true"),   .c_cnt_odd_div_duty_en1  ("false"),
  .c_cnt_hi_div2  (256),  .c_cnt_lo_div2  (256),  .c_cnt_prst2  (1),    .c_cnt_ph_mux_prst2  (0),      .c_cnt_in_src2  ("ph_mux_clk"),  .c_cnt_bypass_en2  ("true"),   .c_cnt_odd_div_duty_en2  ("false"),
  .c_cnt_hi_div3  (1),    .c_cnt_lo_div3  (1),    .c_cnt_prst3  (1),    .c_cnt_ph_mux_prst3  (0),      .c_cnt_in_src3  ("ph_mux_clk"),  .c_cnt_bypass_en3  ("false"),  .c_cnt_odd_div_duty_en3  ("false"),
  .c_cnt_hi_div4  (2),    .c_cnt_lo_div4  (2),    .c_cnt_prst4  (1),    .c_cnt_ph_mux_prst4  (0),      .c_cnt_in_src4  ("ph_mux_clk"),  .c_cnt_bypass_en4  ("false"),  .c_cnt_odd_div_duty_en4  ("false"),
  .c_cnt_hi_div5  (1),    .c_cnt_lo_div5  (1),    .c_cnt_prst5  (1),    .c_cnt_ph_mux_prst5  (0),      .c_cnt_in_src5  ("ph_mux_clk"),  .c_cnt_bypass_en5  ("true"),   .c_cnt_odd_div_duty_en5  ("false"),
  .c_cnt_hi_div6  (1),    .c_cnt_lo_div6  (1),    .c_cnt_prst6  (1),    .c_cnt_ph_mux_prst6  (0),      .c_cnt_in_src6  ("ph_mux_clk"),  .c_cnt_bypass_en6  ("true"),   .c_cnt_odd_div_duty_en6  ("false"),
  .c_cnt_hi_div7  (1),    .c_cnt_lo_div7  (1),    .c_cnt_prst7  (1),    .c_cnt_ph_mux_prst7  (0),      .c_cnt_in_src7  ("ph_mux_clk"),  .c_cnt_bypass_en7  ("true"),   .c_cnt_odd_div_duty_en7  ("false"),
  .c_cnt_hi_div8  (1),    .c_cnt_lo_div8  (1),    .c_cnt_prst8  (1),    .c_cnt_ph_mux_prst8  (0),      .c_cnt_in_src8  ("ph_mux_clk"),  .c_cnt_bypass_en8  ("true"),   .c_cnt_odd_div_duty_en8  ("false"),
  .c_cnt_hi_div9  (1),    .c_cnt_lo_div9  (1),    .c_cnt_prst9  (1),    .c_cnt_ph_mux_prst9  (0),      .c_cnt_in_src9  ("ph_mux_clk"),  .c_cnt_bypass_en9  ("true"),   .c_cnt_odd_div_duty_en9  ("false"),
  .c_cnt_hi_div10 (1),    .c_cnt_lo_div10 (1),    .c_cnt_prst10 (1),    .c_cnt_ph_mux_prst10 (0),      .c_cnt_in_src10 ("ph_mux_clk"),  .c_cnt_bypass_en10 ("true"),   .c_cnt_odd_div_duty_en10 ("false"),
  .c_cnt_hi_div11 (1),    .c_cnt_lo_div11 (1),    .c_cnt_prst11 (1),    .c_cnt_ph_mux_prst11 (0),      .c_cnt_in_src11 ("ph_mux_clk"),  .c_cnt_bypass_en11 ("true"),   .c_cnt_odd_div_duty_en11 ("false"),
  .c_cnt_hi_div12 (1),    .c_cnt_lo_div12 (1),    .c_cnt_prst12 (1),    .c_cnt_ph_mux_prst12 (0),      .c_cnt_in_src12 ("ph_mux_clk"),  .c_cnt_bypass_en12 ("true"),   .c_cnt_odd_div_duty_en12 ("false"),
  .c_cnt_hi_div13 (1),    .c_cnt_lo_div13 (1),    .c_cnt_prst13 (1),    .c_cnt_ph_mux_prst13 (0),      .c_cnt_in_src13 ("ph_mux_clk"),  .c_cnt_bypass_en13 ("true"),   .c_cnt_odd_div_duty_en13 ("false"),
  .c_cnt_hi_div14 (1),    .c_cnt_lo_div14 (1),    .c_cnt_prst14 (1),    .c_cnt_ph_mux_prst14 (0),      .c_cnt_in_src14 ("ph_mux_clk"),  .c_cnt_bypass_en14 ("true"),   .c_cnt_odd_div_duty_en14 ("false"),
  .c_cnt_hi_div15 (1),    .c_cnt_lo_div15 (1),    .c_cnt_prst15 (1),    .c_cnt_ph_mux_prst15 (0),      .c_cnt_in_src15 ("ph_mux_clk"),  .c_cnt_bypass_en15 ("true"),   .c_cnt_odd_div_duty_en15 ("false"),
  .c_cnt_hi_div16 (1),    .c_cnt_lo_div16 (1),    .c_cnt_prst16 (1),    .c_cnt_ph_mux_prst16 (0),      .c_cnt_in_src16 ("ph_mux_clk"),  .c_cnt_bypass_en16 ("true"),   .c_cnt_odd_div_duty_en16 ("false"),
  .c_cnt_hi_div17 (1),    .c_cnt_lo_div17 (1),    .c_cnt_prst17 (1),    .c_cnt_ph_mux_prst17 (0),      .c_cnt_in_src17 ("ph_mux_clk"),  .c_cnt_bypass_en17 ("true"),   .c_cnt_odd_div_duty_en17 ("false"),

  .pll_vco_div    (2),    .pll_cp_current (20),   .pll_bwctrl (4000),

  .pll_output_clk_frequency (C100),              .pll_fractional_division ("1"),     .mimic_fbclk_type ("gclk"),
  .pll_fbclk_mux_1          ("glb"),             .pll_fbclk_mux_2         ("fb_1"),  .pll_m_cnt_in_src ("ph_mux_clk"),  .pll_slf_rst("false")

    ) DDR3_PLL5 (
        .rst           (  RST_PLL       ),
        .refclk        (  CLK_IN        ),
        .outclk        (  PLL1_clk_out  ),
        .locked        (  PLL_LOCKED    ),
        .fboutclk      (                ),
        .fbclk         (  1'b0          ),
        .scanclk       ( phase_sclk     ),
        .phase_en      ( phase_step     ),
        .cntsel        (  5'd2          ),
        .updn          ( phase_updn     ),
        .phase_done    ( phase_done     )
    );

end
// *******************************
// *** End Initiate Altera PLL ***
// *******************************

// ******************************************************************************************************************************************
// ***  LATTICE PLL ********************************************************************************************************************
// ******************************************************************************************************************************************
// end else if (FPGA_VENDOR[0] == "L" || FPGA_VENDOR[0] == "l") begin 


// ********************************
// *** End Initiate Lattice PLL ***
// ********************************
// ******************************************************************************************************************************************
// ***  Xilinx PLL ********************************************************************************************************************
// ******************************************************************************************************************************************
// end else if (FPGA_VENDOR[0] == "X" || FPGA_VENDOR[0] == "x") begin 


// ********************************
// *** End Initiate Xilinx PLL ***
// ********************************
end else initial begin
// ******************************************************************************************************************************************
// ***  Unknown FPGA Vendor **************************************************************************************************************
// ******************************************************************************************************************************************
$warning("****************************************");
$warning("*** BrianHG_DDR3_PLL PARAMETER ERROR ***");
$warning("****************************************************************************");
$warning("*** BrianHG_DDR3_PLL parameter .FPGA_VENDOR(\"%s\") is not supported. ***",FPGA_VENDOR);
$warning("*** Only supported vendors \"Altera\" or \"Intel\".                          ***");
$warning("****************************************************************************");
$error;
$stop;
// ********************************
// *** End Unknown FPGA Vendor  ***
// ********************************
end
endgenerate

assign   DDR3_CLK      = PLL1_clk_out[0];      // DDR3 CK clock running at 1/2 the DQ rate.
assign   DDR3_CLK_WDQ  = PLL1_clk_out[1];      // DDR3 write data clock 90 degree out of phase running at 1/2 the DQ rate.
assign   DDR3_CLK_RDQ  = PLL1_clk_out[2];      // DDR3 phase adjustable read data input clock running at 1/2 the DQ rate.
assign   DDR3_CLK_50   = PLL1_clk_out[3];      // DDR3 clock running at 1/4 the DQ rate.
assign   DDR3_CLK_25   = PLL1_clk_out[4];      // DDR3 clock running at 1/8 the DQ rate.


localparam CMD_CLK_SEL = ((INTERFACE_SPEED[0]=="H" || INTERFACE_SPEED[0]=="h") * 3) + ((INTERFACE_SPEED[0]=="Q" || INTERFACE_SPEED[0]=="q")*4) ;
assign     CMD_CLK     = PLL1_clk_out[CMD_CLK_SEL] ;

generate
initial begin
$warning("*****************************");
$warning("*** BrianHG_DDR3_PLL Info ***");
$warning("*********************************************");
$warning("***      CLK_IN           = %d MHz.     ***",12'(CLK_KHZ_IN/1000));
$warning("***      DDR3_RDQ/WDQ     = %d MTPS.    ***",12'(PLL1_OUT_TRUE_KHZ/500));
$warning("***      DDR3_CLK/RDQ/WDQ = %d MHz.     ***",12'(PLL1_OUT_TRUE_KHZ/1000));
$warning("***      DDR3_WDQ_PHASE   = %d degrees. ***",10'(DDR3_WDQ_PHASE));
$warning("*** True DDR3_WDQ_PHASE   =  %s ps.     ***",DDR3_WDQ_PHASE_pss);
$warning("***      DDR3_RDQ_PHASE   = %d degrees. ***",10'(DDR3_RDQ_PHASE));
$warning("*** True DDR3_RDQ_PHASE   =  %s ps.     ***",DDR3_RDQ_PHASE_pss);
$warning("***      CMD_CLK          = %d MHz.     ***",12'(PLL1_OUT_CMD_CLK_KHZ/1000));
$warning("***      DDR3_CLK_50      = %d MHz.     ***",12'(PLL1_OUT_TRUE_KHZ/2000));
$warning("***      DDR3_CLK_25      = %d MHz.     ***",12'(PLL1_OUT_TRUE_KHZ/4000));
$warning("*********************************************");
end
endgenerate


// **************************************************************************
// Generate an extended reset pulse for at least an extra 64+64 CLK_IN cycles.
// **************************************************************************
localparam         RST_BITS     = 4;
logic              RST_IN_l,RST_IN_l2,RST_IN_l3;
logic [RST_BITS:0] rst_counter  = 0;
assign             RST_PLL      = !rst_counter[RST_BITS];
logic [RST_BITS:0] rst_counter2 = 0;

always @(posedge CLK_IN) begin

// Make the PLL reset only on the low to high transition of the RST_IN.
    RST_IN_l  <= RST_IN;
    RST_IN_l2 <= RST_IN_l;

     if (RST_IN_l && !RST_IN_l2)   rst_counter  <= 0;
else if (!rst_counter[RST_BITS])   rst_counter  <= rst_counter + 1'b1;
end // CLK_IN.

// Generate a reset output on the DDR3_CLK_25 domain.
always @(posedge DDR3_CLK_25) begin

    RST_IN_l3 <= (!rst_counter[RST_BITS]) || !PLL_LOCKED; // transfer reset output conditions to the DDR3_CLK_25

     if (RST_IN_l3)               rst_counter2 <= 0;
else if (!rst_counter2[RST_BITS]) rst_counter2 <= rst_counter2 + 1'b1;
RST_OUT <= !rst_counter2[RST_BITS];
end

endmodule
